package cn.anecansaitin.whimsy.test.explayer;

import cn.anecansaitin.whimsy.common.network.ReplacedPlayerAnimTriggerPack;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.player.Player;
import net.neoforged.neoforge.network.PacketDistributor;
import software.bernie.geckolib.animatable.SingletonGeoAnimatable;
import software.bernie.geckolib.constant.DefaultAnimations;
import software.bernie.geckolib.core.animatable.GeoAnimatable;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager;
import software.bernie.geckolib.core.animation.AnimationController;
import software.bernie.geckolib.core.animation.RawAnimation;
import software.bernie.geckolib.core.object.PlayState;
import software.bernie.geckolib.util.GeckoLibUtil;

import javax.annotation.Nullable;

public class GeoPlayer implements SingletonGeoAnimatable {
    public static final GeoPlayer INSTANCE = new GeoPlayer();
    private LocalPlayer currentPlayer;
    private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);

    private GeoPlayer() {
    }

    @Override
    public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
        controllers.add(DefaultAnimations.genericWalkController(this).setAnimationSpeed(5));
        controllers.add(new AnimationController<GeoAnimatable>(this, "main", 0, (i) -> {
            AnimationController<GeoAnimatable> controller = i.getController();

            if (controller.getAnimationState() == AnimationController.State.STOPPED) {
                return PlayState.STOP;
            }

            return PlayState.CONTINUE;
        })
                .triggerableAnim("idle", IDLE)
                .triggerableAnim("meteor_strike_start", METEOR_STRIKE_START)
                .triggerableAnim("meteor_strike_end", METEOR_STRIKE_END)
                .triggerableAnim("seismic_slam_start", SEISMIC_SLAM_START)
                .triggerableAnim("seismic_slam_end", SEISMIC_SLAM_END));
    }

    @Override
    public AnimatableInstanceCache getAnimatableInstanceCache() {
        return cache;
    }

    @Override
    public double getTick(Object ignore) {
        return currentPlayer.tickCount;
    }

    public void triggerAnim(Player player, @Nullable String controllerName, String animName) {
        if (player.level().isClientSide()) {
            getAnimatableInstanceCache().getManagerForId(player.getId()).tryTriggerAnimation(controllerName, animName);
        } else {
            PacketDistributor.TRACKING_ENTITY_AND_SELF.with(player).send(new ReplacedPlayerAnimTriggerPack(player.getId(), controllerName, animName));
        }
    }

    public LocalPlayer getCurrentPlayer() {
        return currentPlayer;
    }

    public void setCurrentPlayer(LocalPlayer currentPlayer) {
        this.currentPlayer = currentPlayer;
    }

    private static final RawAnimation IDLE = RawAnimation.begin()
            .thenPlay("idle");
    private static final RawAnimation METEOR_STRIKE_START = RawAnimation.begin()
            .thenPlayAndHold("meteor_strike_start");
    private static final RawAnimation METEOR_STRIKE_END = RawAnimation.begin()
            .thenPlayAndHold("meteor_strike_end");
    private static final RawAnimation SEISMIC_SLAM_START = RawAnimation.begin()
            .thenPlayAndHold("seismic_slam_start");
    private static final RawAnimation SEISMIC_SLAM_END = RawAnimation.begin()
            .thenPlayAndHold("seismic_slam_end");
}
